package controllers;

import models.Picture;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.mail.internet.InternetAddress;

import models.ActionLog;
import models.EEntity;
import models.Idea;
import models.Organization;
import models.Plan;
import models.Role;
import models.RoleInEntity;
import models.RoleInOrganization;
import models.SharedIdea;
import models.SharedPlan;
import models.SharedTopic;
import models.Topic;
import models.User;
import play.cache.Cache;
import play.data.binding.As;
import play.data.validation.Email;
import play.data.validation.Required;
import play.data.validation.Validation;
import play.data.validation.Validation.ValidationResult;
import play.db.Model;
import play.db.jpa.Blob;
import play.libs.Codec;
import play.libs.Images;
import play.mvc.Controller;
import sun.net.www.content.text.plain;

public class Users extends Controller {

	/**
	 * @ Author Zeyad Gasser
	 * 
	 * creates a new user and checks if he is already registered by his email
	 * and if the user name is already in use
	 * 
	 * @userStory 8
	 * @component C1
	 * @param name
	 * @param gender
	 * @param userName
	 * @param password
	 * @param dateOfBirth
	 * @param email
	 * @param address
	 */
	public static void createUser(String name, String gender, String userName,
			String password, String password2, String dateOfBirth,
			String email, String address, String code, String randomID,
			Picture picture) {
		validation.required(code).message("Please type the code");
		validation.equals(code, Cache.get(randomID)).message(
				"Invalid code. Please type it again");
		validation.required(name).message("Please enter your full name.");
		validation.required(gender);
		validation.required(userName).message("Please enter a user name");
		validation.required(password).message("Please enter a password");
		validation.required(password2).message(
				"Please enter a confirming password");
		validation.equals(password2, password).message(
				"Please enter a confirming password");
		validation.required(dateOfBirth).message(
				"Please enter your date of birth");
		validation.required(email).message("Please enter your email adress");
		validation.email(email).message(
				"Please type your email in a correct format");

		boolean correctDate = false;
		Date date = null;
		if (dateOfBirth.length() > 0) {
			ValidationResult vr = validation
					.match(dateOfBirth,
							"^((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))$");
			vr.message("The birth date format is not correct make it like yyyy-mm-dd and you better choose from the calender !!!");
			if (vr.ok == true) {
				correctDate = true;
				String[] splitted = dateOfBirth.split("-");
				date = Application.parseDate(splitted[2] + "-" + splitted[1]
						+ "-" + splitted[0]);
			}
		}
		Date nowDate = new Date();
		long elapsed = 0;
		int years = 0;
		if (correctDate) {
			elapsed = nowDate.getTime() - date.getTime();
			years = (int) (elapsed / 1000 / 60 / 60 / 24 / 365);
		}
		if (correctDate && date != null && years < 15) {
			validation.addError(dateOfBirth,
					"The birth date is incompatible. (age>=15)");
			validation.keep();
		}
		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			register();
		}
		User userByEmail = User.getUserByEmail(email);
		User userByUserName = User.getUserInfo(userName);
		if (userByEmail != null || userByUserName != null) {
			render("Application/registeredBefore.html");
		}
		User user = new User(name, gender, userName, password, date, email,
				address).save();

		picture.save();
		user.userPicture = picture;
		user.save();
		picture.user = user;
		picture.save();

		int type = 0;
		if (session.get("username") != null
				&& session.get("username").equalsIgnoreCase("System admin")) {
			type = 1;
			String message = "The system admin has added you to the Idea management"
					+ "company with these username and password :-\n"
					+ "user name :- "
					+ userName
					+ "\nPassword :- "
					+ password
					+ "\n you can change these after log in.";
			Application.sendMail(message, "Added to the system", user);
		}
		String msg = "User name " + user.name + " was registered to the system";
		new ActionLog(msg, user, null).save();
		flash.success("Thanks for registration %s", name);
		Cache.delete(randomID);
		render("Users/registrationSucc.html", type);
	}

	/**
	 * @author Zeyad Gasser
	 * @userStory 8
	 * @component 1
	 * 
	 *            renders the cptcha to the registration form
	 * 
	 * @param id
	 */
	public static void captcha(String id) {
		Images.Captcha captcha = Images.captcha();
		String code = captcha.getText("#E4EAFD");
		Cache.set(id, code, "10mn");
		renderBinary(captcha);
	}

	/**
	 * @author Zeyad Gasser
	 * @userStory 8
	 * @component C1 renders the register view
	 */
	public static void register() {
		// this only my code [Zeyad Gasser]
		String username = session.get("username");
		User userLoggedIn = User.getUserInfo(username);
		if (userLoggedIn != null && !userLoggedIn.isSysteAdmin()) {
			render("Users/userLoggedIn.html");
		}
		String randomID = Codec.UUID();
		render(randomID);
		// till here \/ not mine
		/*
		 * Organization o = new Organization("oName", "oDescription", 0).save();
		 * EEntity e = new EEntity("CS", "csDescription", o).save(); User u;
		 * Topic t = new Topic("myTopic", 0, "a new topic", new Date(), e, u =
		 * new User("sdf", "male", "user", "pass", new Date(), "a@b.c",
		 * "sfst").save()).save(); long tid = t.id, uid = u.id; render(tid,
		 * uid,randomID);
		 */
	}

	/**
	 * method to view all organizations a user is a member in
	 * 
	 * @author Omar Fouda
	 */
	public static void viewOrganizationsOfUser() {

		String userName = session.get("username");
		User user = User.find("userName", userName).first();
		if (user != null) {
			long id = user.id;

			List<RoleInOrganization> roles = user.rolesAndOrganization;
			List<Organization> result = new ArrayList<Organization>();

			if (user.isSysteAdmin()) {
				result = Organization.findAll();
				render(result, user);
			}

			else {
				for (int i = 0; i < roles.size(); i++) {
					if (!result.contains(roles.get(i).organization))
						result.add(roles.get(i).organization);
				}

				render(result, user);
			}
		} else {
			Application.index();
		}
	}

	// public static void organizationLeadHomepage() {
	// render();
	// }

	public static long getUserIdFromUsername(String username) {
		User x = User.find("userName", username).first();
		if (x != null) {
			return x.id;
		}
		return -1;
	}

	/**
	 * allows the system admin to choose a new organization lead for a given
	 * organization. after making sure that the user is logged in and that he is
	 * the system admin it renders html page where the system admin enters the
	 * name or email of the new lead
	 * 
	 * @author Omar Darwish
	 * @param orgID
	 *            The id of the organization that the system admin want to
	 *            change its lead
	 * @see according to validations but mainly html page where the system admin
	 *      enters the new lead name or email.
	 * @story C1-S19
	 */
	public static void chooseNewLead(long orgID) {
		String userName = session.get("username");
		int notAllowed = 1;
		if (userName == null) {
			render(notAllowed);
		}
		User user = User.find("byUsername", userName).first();
		if (user == null) {
			render(notAllowed);
		}
		Organization organization = Organization.findById(orgID);
		if (organization == null
				|| !user.userName.equalsIgnoreCase("System Admin")) {
			render(notAllowed);
		}
		notAllowed = 2;
		LinkedList<String> userNamesAndEmails = new LinkedList<String>();
		List<User> allUsers = User.findAll();
		for (User item : allUsers) {
			if (organization.getOrganizationLead() != null
					&& item.id == organization.getOrganizationLead().id)
				continue;
			userNamesAndEmails.add(item.userName);
			userNamesAndEmails.add(item.email);
		}
		render(notAllowed, orgID, userNamesAndEmails);
	}

	/**
	 * changes the lead of a given organization upon the request of the system
	 * admin by assigning a new lead and removing the old one to be only an idea
	 * developer in the organization.
	 * 
	 * @author Omar Darwish
	 * @param orgID
	 *            The id of the organization that the system admin want to
	 *            change its lead
	 * @param nameOrEmail
	 *            The name or the email of the new lead.
	 * @see html page indicating the succes of the action and that a new lead is
	 *      assigned to the given organization.
	 * @story C1-S19
	 */
	public static void changeLead(long orgID, String nameOrEmail) {
		String userName = session.get("username");
		if (userName == null) {
			error("You are not authorized to view this page");
		}
		User user = User.find("byUsername", userName).first();
		Organization organization = Organization.findById(orgID);
		if (user == null || organization == null) {
			error("You are not authorized to view this page");
		}
		User newLead = null;
		int validate = 0;
		if (nameOrEmail != null) {
			if (!nameOrEmail.contains("@")) {
				newLead = User.find("byUsername", nameOrEmail).first();
			} else {
				newLead = User.find("byEmail", nameOrEmail).first();
			}
			if (newLead == null) {
				validate = 1;
			} else if (organization.getOrganizationLead() != null
					&& newLead.id == organization.getOrganizationLead().id) {
				validate = 2;
			}
		}
		validation.required(nameOrEmail)
				.message("You must choose the new lead");
		if (validate == 1) {
			validation.addError(nameOrEmail,
					"You must a choose an existing user");
		} else if (validate == 2) {
			validation.addError(nameOrEmail,
					"Redundant change :- same old lead chose??!!");
		}
		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			chooseNewLead(orgID);
		}
		User oldLead = organization.getOrganizationLead();
		Role lead = Role.find("byDescription", "OrganizationLead").first();
		Role ideaDeveloper = Role.find("byDescription", "IdeaDeveloper")
				.first();
		if (oldLead != null) {
			RoleInOrganization oldRoleOfOldLead = RoleInOrganization
					.find("byRoleAndOrganizationAndUser", lead, organization,
							oldLead).first();
			oldRoleOfOldLead.role = ideaDeveloper;
			oldRoleOfOldLead.save();
		}
		List<RoleInOrganization> allRoles = RoleInOrganization.findAll();
		boolean flag = false;
		for (RoleInOrganization item : allRoles) {
			if (item.organization.id == organization.id
					&& item.user.id == newLead.id) {
				item.role = lead;
				item.save();
				flag = true;
				break;
			}
		}
		if (!flag) {
			RoleInOrganization newRole = new RoleInOrganization(organization,
					newLead, lead).save();
		}
		String message = null;
		if (oldLead != null) {
			message = "Sorry but the system admin decided that You will no longer be the organization lead of  "
					+ organization.name
					+ " organization and "
					+ newLead.name
					+ " has become the new Lead";
			Application.sendMail(message, "Change Organization Lead", oldLead);
		}
		message = "Congratulations :- The system admin decided that You will be the new organization lead  of "
				+ organization.name + " organization";
		Application.sendMail(message, "Change Organization Lead", newLead);
		List<User> Notified = organization.getOrganizersList();
		message = newLead.name + " is now the lead of" + organization.name
				+ "organization.";
		for (User item : Notified) {
			Application.sendMail(message, "Change Organization Lead", item);
		}
		render(organization, newLead);
	}

	/**
	 * It fetches the ideas,topics and plans shared on the wall of the logged in
	 * user and renders them
	 * 
	 * @author Islam Al-Aarag
	 * @story C4S66
	 */
	public static void showWall() {
		String userName = session.get("username");
		User user = null;
		if (userName != null)
			user = User.find("byUserName", userName).first();
		if (user != null) {
			List<SharedIdea> sharedIdeas = user.sharedIdeas;
			Collections.reverse(sharedIdeas);
			List<SharedTopic> sharedTopics = user.sharedTopics;
			Collections.reverse(sharedTopics);
			List<SharedPlan> sharedPlans = user.sharedPlans;
			Collections.reverse(sharedPlans);
			for (SharedIdea idea : sharedIdeas) {
				idea.history = Application.dateMap(idea.postedAt);
				idea.save();
				System.out.println(idea.sharer.name);
			}
			for (SharedTopic topic : sharedTopics) {
				topic.history = Application.dateMap(topic.postedAt);
				topic.save();
			}
			for (SharedPlan plan : sharedPlans) {
				plan.history = Application.dateMap(plan.postedAt);
				plan.save();
			}
			render(sharedIdeas, sharedTopics, sharedPlans);
		}
	}

	/**
	 * This method is responsible for rendering the user profile. If the user is
	 * not logged in or the user profile does not exist, an according error
	 * message will be displayed.
	 * 
	 * @param username
	 *            The user name of the profile to be shown. If null, the current
	 *            session user will be viewed.
	 * @story C1-S13
	 * @autor Johannes Schmidt (schmjoha@googlemail.com)
	 */
	public static void viewUserProfile(String username) {
		User user = null;
		boolean showName = true;
		boolean showDOB = true;
		boolean showAddress = true;
		boolean showEmail = true;
		String sessionUser = session.get("username");

		if (username != null && !username.equals("")) {
			user = User.find("byUsername", username).first();
			if (user != null) {
				showName = user.profileVisibility.contains("name;");
				showDOB = user.profileVisibility.contains("dateOfBirth;");
				showAddress = user.profileVisibility.contains("address;");
				showEmail = user.profileVisibility.contains("email;");
			}

		} else {
			user = User.find("byUsername", sessionUser).first();
		}
		boolean isOrganizer = false;
		boolean isOrganizationLead = false;
		if (user != null) {
			List<Organization> orgs = Organization.findAll();
			List<EEntity> entities = EEntity.findAll();
			for (Organization o : orgs) {
				long iD = o.id;
				if (user.isOrganizationLead(iD)) {
					isOrganizationLead = true;
					break;
				}
			}
			for (EEntity e : entities) {
				if (user.isOrganizer(e.id)) {
					isOrganizer = true;
					break;
				}
			}
		}
		boolean highPosition = isOrganizer || isOrganizationLead;

		boolean isSystemAdmin = false;
		if (sessionUser != null) {
			isSystemAdmin = sessionUser.equalsIgnoreCase("System Admin");
		}

		render(user, showName, showDOB, showAddress, showEmail, highPosition,
				isSystemAdmin);
	}

	/**
	 * checks that the user logged in is a system admin and then directs him to
	 * the register page to register for a new user.
	 * 
	 * @author Omar Darwish
	 * @see New user sign up page
	 * @story C1-S1
	 */
	public static void adminCreateUser() {
		String userName = session.get("username");
		if (userName == null || !userName.equalsIgnoreCase("System admin"))
			renderTemplate("/users/notAllowed.html");
		User user = User.find("byUserName", userName).first();
		if (user == null)
			renderTemplate("/users/notAllowed.html");
		render("/Users/register.html");
	}

	/**
	 * allows a system admin to choose a user to delete him from the company
	 * itself.So it checks that the user is the system admin and then renders
	 * html page to let him choose the user to be deleted. >>>>>>> .r1175
	 * 
	 * @author Omar Darwish
	 * @see html page for the system admin to choose the user.
	 * @story C1-S1
	 */
	public static void chooseDeletedUser() {
		String userName = session.get("username");
		if (userName == null || !userName.equalsIgnoreCase("System admin"))
			renderTemplate("/users/notAllowed.html");
		User user = User.find("byUserName", userName).first();
		if (user == null)
			renderTemplate("/users/notAllowed.html");
		LinkedList<String> userNamesAndEmails = new LinkedList<String>();
		List<User> allUsers = User.findAll();
		for (User item : allUsers) {
			if (item.userName.equalsIgnoreCase("System admin"))
				continue;
			userNamesAndEmails.add(item.userName);
			userNamesAndEmails.add(item.email);
		}
		render(userNamesAndEmails);
	}

	/**
	 * allows the system admin to delete a certian user provided his username of
	 * his email.
	 * 
	 * @author Omar Darwish
	 * @param nameOrEmail
	 *            the user name or the email of the user to be deleted.
	 * @see a page clarifying the succes of the action.
	 * @story C1-S1
	 */
	public static void deleteUser(String nameOrEmail) {
		validation.required(nameOrEmail).message("You must choose the user");

		User user = null;
		if (nameOrEmail != null) {
			if (!nameOrEmail.contains("@")) {
				user = User.find("byUsername", nameOrEmail).first();
			} else {
				user = User.find("byEmail", nameOrEmail).first();
			}
			if (user == null) {
				validation.addError(nameOrEmail,
						"You must a choose an existing user");
			}
		}
		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			chooseDeletedUser();
		}
		List<Organization> organizations = Organization.findAll();
		int flag1 = 0;
		LinkedList<Organization> outOrganizations = new LinkedList<Organization>();
		for (Organization org : organizations) {
			if (org.getOrganizationLead() != null
					&& org.getOrganizationLead().id == user.id) {
				flag1 = 1;
				outOrganizations.add(org);
			}
		}
		List<EEntity> entities = EEntity.findAll();
		int flag2 = 0;
		LinkedList<EEntity> outEntities = new LinkedList<EEntity>();
		for (EEntity entity : entities) {
			if (entity.getOrganizers().contains(user)
					&& entity.getOrganizers().size() == 1) {
				flag2 = 1;
				outEntities.add(entity);
			}
		}

		user.cascadeDelete();
		render(flag1, flag2, outOrganizations, outEntities);
	}

	/**
	 * check that the logged in user is the system admin and allows him to
	 * choose a user to edit his information by rendering html page for this.
	 * 
	 * @author Omar Darwish
	 * @see html page for the system admin to choose the user to be edited
	 * @story C1-S1
	 */
	public static void adminEditProfile() {
		String userName = session.get("username");
		if (userName == null || !userName.equalsIgnoreCase("System admin"))
			renderTemplate("/users/notAllowed.html");
		User user = User.find("byUserName", userName).first();
		if (user == null)
			renderTemplate("/users/notAllowed.html");
		LinkedList<String> userNamesAndEmails = new LinkedList<String>();
		List<User> allUsers = User.findAll();
		for (User item : allUsers) {
			if (item.userName.equalsIgnoreCase("System admin"))
				continue;
			userNamesAndEmails.add(item.userName);
			userNamesAndEmails.add(item.email);
		}
		render(userNamesAndEmails);
	}

	/**
	 * gets the user to be edited from his mail or user name and renders the
	 * html page responsible for letting the system admin edits user information
	 * 
	 * @author Omar Darwish
	 * @param nameOrEmail
	 *            the username or the email of the user to be edited.
	 * @see html page for the system admin to edit user information
	 * @story C1-S1
	 * 
	 */
	public static void adminConfirmEditProfile(String nameOrEmail) {
		validation.required(nameOrEmail).message("You must choose the user");
		User user = null;
		if (nameOrEmail != null) {
			if (!nameOrEmail.contains("@")) {
				user = User.find("byUsername", nameOrEmail).first();
			} else {
				user = User.find("byEmail", nameOrEmail).first();
			}
			if (user == null) {
				validation.addError(nameOrEmail,
						"You must a choose an existing user");
			}
		}
		if (validation.hasErrors() && (user == null || nameOrEmail == null)) {
			params.flash();
			validation.keep();
			adminEditProfile();
		}
		render(user);
	}

	/**
	 * edits a given user upon system admin request.It gets the new information
	 * of the user given by the system admin and changes the user personal
	 * information according to the new information.
	 * 
	 * @author Omar Darwish
	 * @param name
	 *            user name of the user.
	 * @param newName
	 *            new name of the user.
	 * @param newAddress
	 *            new address of the user.
	 * @param newGender
	 *            new gender of the user.
	 * @param newDateOfBirth
	 *            new date of birth of the user.
	 * @see html page to clarify succes of the edit action.
	 * @story C1-S1
	 */
	public static void adminDoneEditProfile(String name, String newName,
			String newAddress, String newGender, String newDateOfBirth) {
		validation.required(newName).message("You must enter the new name");
		validation.required(newAddress).message(
				"You must enter the new address");
		validation.required(newGender).message("You must enter the new gender");
		validation.required(newDateOfBirth).message(
				"You must enter the new date of birth");
		boolean correctDate = false;
		Date date = null;
		if (newDateOfBirth.length() > 0) {
			ValidationResult vr = validation
					.match(newDateOfBirth,
							"^((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))$");
			vr.message("The birth date format is not correct make it like yyyy-mm-dd and you better choose from the calender !!!");
			if (vr.ok == true) {
				correctDate = true;
				String[] splitted = newDateOfBirth.split("-");
				date = Application.parseDate(splitted[2] + "-" + splitted[1]
						+ "-" + splitted[0]);
			}
		}
		Date nowDate = new Date();
		long elapsed = 0;
		int years = 0;
		if (correctDate) {
			elapsed = nowDate.getTime() - date.getTime();
			years = (int) (elapsed / 1000 / 60 / 60 / 24 / 365);
		}
		if (correctDate && date != null && years < 15) {
			validation.addError(newDateOfBirth,
					"The birth date is incompatible. (age>=15)");
			validation.keep();
		}
		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			adminConfirmEditProfile(name);
		} else {
			User user;
			user = User.find("byUsername", name).first();
			if (user == null) {
				adminEditProfile();
			}
			user.name = newName;
			user.address = newAddress;
			user.dateOfBirth = date;
			user.gender = newGender;
			user.save();
			String message = "The system admin has modified some of you information\n"
					+ "Here is your personal info after modification :-\n"
					+ "Name :-"
					+ newName
					+ "\nGender :-"
					+ newGender
					+ "\nAddress :-"
					+ newAddress
					+ "\nDate Of Birth :-"
					+ newDateOfBirth;
			Application.sendMail(message, "Personal Information change", user);
			render(user);
		}
	}

	/**
	 * 
	 * @param message
	 *            The optional message shown after submitting changes.
	 * @param error
	 *            The optional error messages after submitting changes.
	 * 
	 * @author Johannes Schmidt (schmjoha@googlemail.com)
	 * @story C1S16
	 */
	public static void editUserProfile(String message, String error) {
		User user = null;
		String sessionUser = session.get("username");
		if (sessionUser != null) {
			user = User.find("byUsername", sessionUser).first();
		}

		boolean showName = user.profileVisibility.contains("name;");
		boolean showDOB = user.profileVisibility.contains("dateOfBirth;");
		boolean showAddress = user.profileVisibility.contains("address;");
		boolean showEmail = user.profileVisibility.contains("email;");
		render(user, message, error, showName, showDOB, showAddress, showEmail);
	}

	/**
	 * Edits user profile information upon request by the user within the
	 * according view (editUserProfile.html).
	 * 
	 * @param username
	 * @param address
	 * @param showName
	 * @param showDOB
	 * @param showAddress
	 * @param showEmail
	 * @param oldPassword
	 * @param newPassword
	 * @param confirmPassword
	 * @param oldEmail
	 * @param newEmail
	 * @param confirmEmail
	 * 
	 * @author Johannes Schmidt (schmjoha@googlemail.com)
	 * @story C1S16
	 */
	public static void submitProfileChanges(String username, String address,
			String showName, String showDOB, String showAddress,
			String showEmail, String oldPassword, String newPassword,
			String confirmPassword, String oldEmail, String newEmail,
			String confirmEmail) {

		String message = "";
		String error = "";

		String sessionUsername = session.get("username");
		User sessionUser = User.getUserInfo(sessionUsername);

		// Change user address
		if (!address.equals("") && !address.equals(sessionUser.address)) {
			sessionUser.address = address;
			message += "Successfully updated address information. ";
		}

		// Change profile viewing preferences
		String oldProfileVisibility = sessionUser.profileVisibility;
		sessionUser.profileVisibility = "";
		if (showName != null)
			sessionUser.profileVisibility += "name;";
		if (showDOB != null)
			sessionUser.profileVisibility += "dateOfBirth;";
		if (showAddress != null)
			sessionUser.profileVisibility += "address;";
		if (showEmail != null)
			sessionUser.profileVisibility += "email;";
		if (!oldProfileVisibility.equals(sessionUser.profileVisibility))
			message += "Successfully updated viewing preferences. ";

		// Change password
		boolean oldPwSet = !oldPassword.equals("");
		boolean newPwSet = !newPassword.equals("");
		boolean confirmPwSet = !confirmPassword.equals("");

		if (oldPwSet || newPwSet || confirmPwSet) {
			if (oldPwSet && newPwSet && confirmPwSet) {
				if (oldPassword.equals(sessionUser.password)
						&& newPassword.equals(confirmPassword)) {
					if (checkPassword(newPassword)) {
						sessionUser.password = newPassword;
						message += "The password has successfully been changed.";
					} else {
						error += "The new password has to contain at least one big, one small letter, one number, "
								+ "may contain only a-z, A-Z and 0-9 and has to have a minimum number of 8 characters. ";
					}
				} else if (!oldPassword.equals(sessionUser.password)) {
					error += "The given old password is not correct. ";
				} else {
					error += "The given confirmation password does not match the new password. ";
				}
			} else {
				error += "Please fill out all the fields required, "
						+ "in order to change your password. ";
			}
		}

		// Change email address
		boolean oldMailSet = !oldEmail.equals("");
		boolean newMailSet = !newEmail.equals("");
		boolean confirmMailSet = !confirmEmail.equals("");

		if (oldMailSet || newMailSet || confirmMailSet) {
			if (oldMailSet && newMailSet && confirmMailSet) {
				if (oldEmail.equals(sessionUser.email)
						&& newEmail.equals(confirmEmail)) {
					if (checkMail(newEmail)) {
						sessionUser.email = newEmail;
						message += "The email address has successfully been changed. ";
					} else {
						error += "The new email is not a valid email address. ";
					}
				} else if (!oldEmail.equals(sessionUser.email)) {
					error += "The given old email address is not correct. ";
				} else {
					error += "The given confirmation email does not match the new email address. ";
				}
			} else {
				error += "Please fill out all the fields required, "
						+ "in order to change your email address. ";
			}
		}
		sessionUser.save();

		// Create log record if user preferences have been changed
		String logMessage = "User name " + sessionUser.userName
				+ " edited his profile";
		if (error.equals("") || !message.equals(""))
			new ActionLog(logMessage, sessionUser, null).save();

		editUserProfile(message, error);
	}

	/**
	 * Checks if a given email is a valid email address.
	 * 
	 * @param mail
	 *            The email address string to be checked.
	 * @return Returns true if the email address is valid, false if it is not.
	 * 
	 * @author Johannes Schmidt (schmjoha@googlemail.com)
	 * @story C1S16
	 */
	public static boolean checkMail(String mail) {
		String p = "(^[\\w\\.\\-]{1,})@([\\w\\.\\-]{3,})(\\.)([a-zA-Z]{2,}$)";
		Pattern pattern = Pattern.compile(p);
		Matcher matcher = pattern.matcher(mail);
		return matcher.matches();
	}

	/**
	 * Checks if a given password contains at least one big, one small letter,
	 * one number and has a length of 8 minimum.
	 * 
	 * @param password
	 *            The password string to be checked.
	 * @return Returns true if the password is valid, false if it is not.
	 * 
	 * @author Johannes Schmidt (schmjoha@googlemail.com)
	 * @story C1S16
	 */
	public static boolean checkPassword(String password) {
		boolean smallLetter = false;
		boolean bigLetter = false;
		boolean number = false;
		boolean noInvalidCharacter = true;
		boolean lengthGreater7 = password.length() > 7;

		for (int i = 0; i < password.length(); i++) {
			if (password.charAt(i) >= 65 && password.charAt(i) <= 90)
				bigLetter = true;
			else if (password.charAt(i) >= 97 && password.charAt(i) <= 122)
				smallLetter = true;
			else if (password.charAt(i) >= 48 && password.charAt(i) <= 57)
				number = true;
			else
				noInvalidCharacter = false;
		}
		return smallLetter && bigLetter && number && noInvalidCharacter
				&& lengthGreater7;
	}

	/**
	 * Given a user id, it added the user with this id ( if exists) to the list
	 * of blocked user of this user if not already blocked
	 * 
	 * @author Islam Al-Aarag
	 * @story C4S71
	 * @param blockedUser
	 *            the id of the user to be blocked by the logged in user
	 */
	public static void block(long blockedUser) {
		String userName = session.get("username");
		User user = null;
		if (userName != null)
			user = User.find("byUserName", userName).first();
		if (user != null) {
			if (user.id != blockedUser) {
				user.block(blockedUser);
				flash.success(((User) User.findById(blockedUser)).name
						+ " has been successfully blocked");
				System.out.println(user.sharedIdeas.size());
			} else {
				flash.success("Sorry, you can not block yourself");
			}
			showWall();
		}
	}

	/**
	 * Given a user id, it unblocks the user (i.e: remove it from list of
	 * blocked users) if it still exists in the system
	 * 
	 * @author Islam Al-Aarag
	 * @story C4S71
	 * @param unBlockedUser
	 *            the id of the user to unblock
	 */
	public static void unBlock(long unBlockedUser) {
		String userName = session.get("username");
		User user = null;
		if (userName != null)
			user = User.find("byUserName", userName).first();
		if (user != null) {
			user.unBlock(unBlockedUser);
			flash.success(((User) User.findById(unBlockedUser)).name
					+ " has been successfully unblocked");
			showWall();
		}
	}

	/**
	 * Given a user id, it checks whether this user has blocked the provided
	 * user or not (non existing users are considered to be blocked if they
	 * can't perform any action)
	 * 
	 * @author Islam Al-Aarag
	 * @story C4S71
	 * @param userToCheck
	 *            the id of the user to check for his status
	 * @return true the user is blocked ,false the user is not blocked
	 */
	public static boolean isBlocked(long userToCheck) {
		String userName = session.get("username");
		User user = null;
		if (userName != null)
			user = User.find("byUserName", userName).first();
		if (user != null) {
			return user.isBlocked(userToCheck);
		} else {
			return true;
		}
	}

	/**
	 * Used as a controller method to render the page where the user is prompted
	 * to enter his e-mail to retrieve his login info
	 * 
	 * @author Sherif Ayad
	 */
	public static void forgotPassword() {
		render();
	}

	/**
	 * Used to get the user who submitted his mail address, and then send the
	 * user name and the password to that e-mail
	 * 
	 * @param mail
	 *            The e-mail address of the user who wants to retrieve his login
	 *            info
	 * @author Sherif Ayad
	 */
	public static void restorePassword(String mail) {
		System.out.println(mail);
		User user = User.find("byEmail", mail).first();
		if (user == null) {
			Validation.addError("", "Invalid E-mail address!", "");
			Validation.keep();
			forgotPassword();
		} else {
			String userName = user.userName;
			String password = user.password;
			String msg = "Your user name is: " + userName
					+ "\nYour password is: " + password;
			Application.sendMail(msg, "Idea Managemnet Tool Login Details",
					user);
			flash.success("Your login info was successully sent to your e-mail");
			try {
				Secure.login();
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public static void getMyTopics() {
		String username = session.get("username");
		notFoundIfNull(username);
		User user = User.getUserInfo(username);
		notFoundIfNull(user);
		List<Topic> myTopics = user.createdTopics;
		render("Browse/My Topics.html", myTopics);
	}

	public static void getMyIdeas() {
		String username = session.get("username");
		notFoundIfNull(username);
		User user = User.getUserInfo(username);
		notFoundIfNull(user);
		List<Idea> ideas = user.createdIdeas;
		List<Idea> myIdeas = new LinkedList<Idea>();
		for (Idea idea : ideas) {
			if (!idea.isDraft) {
				myIdeas.add(idea);
			}
		}
		render("Browse/My Ideas.html", myIdeas);
	}

	/**
	 * method to call the html page to change a user's picture
	 * 
	 * @author omar fouda
	 * @param userId
	 *            , id of the user that want's to change his picture
	 */
	public static void changeProfilePicture(long userId) {
		User user = User.findById(userId);
		render(user);
	}

}
